import {Injectable} from '@angular/core';
import {NzNotificationService} from 'ng-zorro-antd';
import {SettingUrl} from '../../public/setting/setting_url';
import {Setting} from '../../public/setting/setting';
import {HttpClient, HttpErrorResponse} from '@angular/common/http';
import {FurtherData, ResponseConfig, ResponseError} from 'src/app/public/setting/model';
import {Observable, throwError} from 'rxjs';
import {catchError} from 'rxjs/operators';
import {AuthService} from "../../public/service/auth-service";

@Injectable({
  providedIn: 'root'
})
export class IdeService {

  public deviceData: any = localStorage.getItem(Setting.storage.deviceData) ? JSON.parse(localStorage.getItem(Setting.storage.deviceData)) : null;
  public projectVersionId = Setting.projectVersionId || localStorage.getItem(Setting.storage.projectVersionId);
  public accessToken = AuthService.getAuthorizationToken();
  public deviceIp = this.deviceData ? `${this.deviceData.ip}:${this.deviceData.port}` : ''; // device ip

  constructor(private notification: NzNotificationService,
              private http: HttpClient) {
  }

  /**
   * loadProjects
   */
  loadProjectsFromFurther(): Observable<FurtherData> {
    const url = SettingUrl.URL.furtherApi.loadProjectsDataFromFurther(this.projectVersionId, this.accessToken);
    return this.http.get<FurtherData>(url)
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  /**
   * get device battery power
   */
  getDeviceElectric(): Observable<ResponseConfig> {
    const url = SettingUrl.URL.localApi.battery(this.deviceIp);
    return this.http.get<ResponseConfig>(url)
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  /**
   * run code
   */
  projectStart(data: any[]) {
    const url = SettingUrl.URL.localApi.start(this.deviceIp);
    return this.http.post<ResponseConfig>(url, data)
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  /**
   * bind device after got token
   * @param requestData {token: string}
   */
  bindDevice(requestData: { token: string }) {
    const url = SettingUrl.URL.bind;
    return this.http.post<ResponseConfig>(url, null, {params: requestData})
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  /**
   * create file to further
   * @param requestData {path: string, content: string}
   */
  createFileToFurther(requestData: { path: string, content: string }) {
    const url = SettingUrl.URL.furtherApi.createFile(this.projectVersionId, this.accessToken);
    return this.http.post(url, requestData)
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  /**
   * delete file from further
   */
  deleteFurtherFile(id: string) {
    const url = SettingUrl.URL.furtherApi.updateFile(this.projectVersionId, this.accessToken, id);
    return this.http.delete(url)
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  /**
   * update file of further
   * @param requestData {path: string, content: string, id:string}
   */
  updateFileForFurther(requestData: { path: string, content: string, id: string }) {
    const url = SettingUrl.URL.furtherApi.updateFile(this.projectVersionId, this.accessToken, requestData.id);
    return this.http.put(url, requestData)
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  /**
   * sign in remote by further token and account
   * @param requestData: {accountId:string, username:string, email:string}
   */
  signInByFurtherToken(requestData: { accountId: string, username: string, email: string }) {
    const url = SettingUrl.URL.login.furtherLogin;
    const data = {
      ...requestData,
      sessionToken: this.accessToken
    };
    return this.http.put<ResponseConfig>(url, null, {params: data})
      .pipe(
        catchError(err => this.handleError(err))
      );
  }

  private handleError(error: HttpErrorResponse) {
    let err: ResponseError;
    if (typeof error.error === "string" || typeof error.error.error === "string") {
      err = {
        code: error.status,
        message: error.statusText,
        name: String(error.status),
        statusCode: error.status
      };
    }else if (typeof error.error.error === "object") {
      err = error.error.error;
    }
    this.notification.error(err.name, err.message);
    return throwError(err);
  };

}
